﻿using System;

using BrightSword.Crucible;
using BrightSword.SwissKnife;

using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Tests.BrightSword.SwissKnife
{
    [TestClass]
    public class CommandLineArgumentHelperTests
    {
        [TestMethod]
        public void Test_GivenNoArguments_CommandLineArgumentHelper_MustNotCrash()
        {
            var instance = new CommandLineArgumentHelper();
            Assert.IsNotNull(instance);
            Assert.IsFalse(instance.HelpRequested);
            Assert.AreEqual(0,
                            instance.Count);
        }

        [TestMethod]
        public void Test_GivenValidArguments_CommandLineArgumentHelper_MustNotCrash()
        {
            var instance = new CommandLineArgumentHelper("--help",
                                                         "--name=foo",
                                                         "--weight=bar");
            Assert.IsNotNull(instance);
            Assert.IsTrue(instance.HelpRequested);
            Assert.AreEqual(3,
                            instance.Count);
            Assert.AreEqual("foo",
                            instance["name"]);
            Assert.AreEqual("foo",
                            instance["Name"]);
            Assert.AreEqual("bar",
                            instance["WEIGHT"]);
            Assert.AreEqual("bar",
                            instance.GetArgumentValue("weight",
                                                      _ => _,
                                                      String.Empty));
        }

        [TestMethod]
        public void Test_GivenArgumentsWithoutMinusMinus_CommandLineArgumentHelper_MustNotCrash()
        {
            var instance = new CommandLineArgumentHelper("help",
                                                         "name=foo",
                                                         "weight=bar");
            Assert.IsNotNull(instance);
            Assert.IsTrue(instance.HelpRequested);
            Assert.AreEqual(3,
                            instance.Count);
            Assert.AreEqual("foo",
                            instance["name"]);
            Assert.AreEqual("foo",
                            instance["Name"]);
            Assert.AreEqual("bar",
                            instance["WEIGHT"]);
            Assert.AreEqual("bar_of_soap",
                            instance.GetArgumentValue("weight",
                                                      _ => String.Format("{0}_of_soap",
                                                                         _),
                                                      String.Empty));

            ExceptionHelper.ExpectException<ArgumentOutOfRangeException>(() =>
                                                                         {
                                                                             var result = instance["date"];
                                                                         });

            Assert.AreEqual(String.Empty,
                            instance.GetArgumentValue("date",
                                                      _ => String.Format("{0}_of_soap",
                                                                         _),
                                                      String.Empty));
        }

        [TestMethod]
        public void Test_GivenArgumentValuesQuotedWithEmbeddedSpaces_CommandLineArgumentHelper_MustNotCrash()
        {
            var instance = new CommandLineArgumentHelper("help",
                                                         "name='foo is fun'",
                                                         "weight=\"bar is not fun\"");
            Assert.IsNotNull(instance);
            Assert.IsTrue(instance.HelpRequested);
            Assert.AreEqual(3,
                            instance.Count);
            Assert.AreEqual("'foo is fun'",
                            instance["name"]);
            Assert.AreEqual("'foo is fun'",
                            instance["Name"]);
            Assert.AreEqual("\"bar is not fun\"",
                            instance["WEIGHT"]);
            Assert.AreEqual("\"bar is not fun\"",
                            instance.GetArgumentValue("weight",
                                                      _ => _,
                                                      String.Empty));
        }

        [TestMethod]
        public void Test_ObsoleteMethods()
        {
            var args = new[]
                       {
                           "help", "name='foo is fun'", "weight=\"bar is not fun\""
                       };

            Assert.IsTrue(args.HelpRequested());
            Assert.IsTrue(args.IsArgumentSpecified("name"));
            Assert.IsFalse(args.IsArgumentSpecified("date"));
            Assert.AreEqual("'foo is fun'",
                            args.GetArgumentValue("Name",
                                                  _ => _,
                                                  String.Empty));
        }
    }
}